using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace Arcane.Source.Utils;

public struct CoroutineExecutor
{
    private readonly List<Coroutine> _coroutines;

    public int Count => _coroutines.Count;

    public CoroutineExecutor()
    {
        _coroutines = [];

    }

    public void StartCoroutine(IEnumerator co)
    {
        _coroutines.Add(new(co));
    }

    public void Tick()
    {
        _coroutines.RemoveAll(co => !co.MoveNext());
    }
}

struct Coroutine
{
    private readonly Stack<IEnumerator> _stack;
    public Coroutine(IEnumerator co)
    {
        _stack = new();
        _stack.Push(co);
    }

    public readonly bool MoveNext()
    {
        if (_stack.Peek().MoveNext())
        {
            if (_stack.Peek().Current is IEnumerator co)
            {
                _stack.Push(co);
            }
            return true;
        }
        else 
        {
            _stack.Pop();
            return _stack.Count > 0;
        }
    }

    public static IEnumerator WaitForTick(int tick)
    {
        while (tick-- > 0) yield return null;
    }

    public static IEnumerator WaitWhile(Func<bool> predicate)
    {
        while (predicate()) yield return null;
    }
}